package org.sraosha.creator.handler;

import org.sraosha.creator.constants.DatabaseConstants;
import org.sraosha.creator.constants.TemplateConstants;
import org.sraosha.creator.manager.IDatabaseManager;
import org.sraosha.creator.manager.MysqlManager;
import org.sraosha.creator.manager.OracleManager;
import lombok.extern.slf4j.Slf4j;
import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.info.GraphLayout;
import org.sraosha.creator.pojo.*;

import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * 处理器类的抽象类
 *
 */
@Slf4j
public abstract class AbstractHandler {

    protected IDatabaseManager databaseManager;
    protected Model model;
    protected Mapper mapper;
    protected MapperXml mapperXml;
    protected Service service;
    protected ServiceImpl serviceImpl;
    protected Controller controller;
    protected DataTransferObject dataTransferObject;

    public AbstractHandler() {
        // 确定数据库类型
        if (DatabaseConstants.ORACLE.equalsIgnoreCase(DatabaseConstants.DATABASE_TYPE)) {
            databaseManager = new OracleManager();
        }
        if (DatabaseConstants.MYSQL.equalsIgnoreCase(DatabaseConstants.DATABASE_TYPE)) {
            databaseManager = new MysqlManager();
        }

        // 初始化成员变量
        this.init();
    }

    /**
     * 初始化成员变量
     */
    protected void init() {
        // 初始化model
        model = new Model();
        model.setPackageName(TemplateConstants.MODEL_PACKAGE_NAME);

        // 初始化mapper
        mapper = new Mapper();
        mapper.setBasePackageName(TemplateConstants.MAPPER_BASE_PACKAGE_NAME);
        mapper.setPackageName(TemplateConstants.MAPPER_PACKAGE_NAME);

        // 初始化mapperXml
        mapperXml = new MapperXml();
        mapperXml.setPackageName(TemplateConstants.MAPPER_XML_PACKAGE_NAME);

        // 初始化service
        service = new Service();
        service.setPackageName(TemplateConstants.SERVICE_PACKAGE_NAME);

        // 初始化serviceImpl
        serviceImpl = new ServiceImpl();
        serviceImpl.setPackageName(TemplateConstants.SERVICE_IMPL_PACKAGE_NAME);

        // 初始化controller
        controller = new Controller();
        controller.setPackageName(TemplateConstants.CONTROLLER_PACKAGE_NAME);

        // 初始化viewObject
        dataTransferObject = new DataTransferObject();
        dataTransferObject.setPackageName(TemplateConstants.VIEW_OBJECT_PACKAGE_NAME);
    }

    protected void handle() {
        log.info("开始执行AbstractHandler类的handle方法");

        try {
            ResultSet resultSet = databaseManager.findUserTable();
//            ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
//            int columnCount = resultSetMetaData.getColumnCount();

            String[] tableNameArray = DatabaseConstants.GENERATE_TABLE_NAME.replace("[", "").replace("]", "").trim().split(",");

            while (resultSet.next()) {
                String tableName = databaseManager.getTableName(resultSet);
                log.info("数据库中的表名：" + tableName);

                // 如果表名匹配，则生成对应的文件
                if (null != tableNameArray && tableNameArray.length > 0) {
                    for (int i = 0; i < tableNameArray.length; i++) {
                        if (tableNameArray[i].trim().equalsIgnoreCase(tableName)) {
                            log.info("表名：" + tableName + "匹配");

                            collect(tableName);
                            createModel();
                            createMapper();
                            createXML();
                            createService();
                            createServiceImpl();
                            createController();
                            createViewObject();
                        }
                    }
                } else {
                    log.warn("配置文件config.properties中的属性generate.tableName为空");
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        //输出对象内部信息
        System.out.println("对象内部大小==>" + ClassLayout.parseInstance(this.model).toPrintable());

        //输出对象外部信息，包含引用对象
        System.out.println(GraphLayout.parseInstance(this.model).toPrintable());

        //输出对象大小
        System.out.println(GraphLayout.parseInstance(this.model).totalSize());
    }

    /**
     * 收集数据，填充到model中
     * @param tableName
     */
    abstract void collect(String tableName);

    /**
     * 根据模板，创建model文件
     */
    abstract void createModel();

    /**
     * 根据模板，创建mapper文件
     */
    abstract void createMapper();

    /**
     * 根据模板，创建xml文件
     */
    abstract void createXML();

    /**
     * 根据模板，创建service文件
     */
    abstract void createService();

    /**
     * 根据模板，创建serviceImpl文件
     */
    abstract void createServiceImpl();

    /**
     * 根据模板，创建controller文件
     */
    abstract void createController();

    /**
     * 根据模板，创建dto文件
     */
    abstract void createViewObject();
}
